# coding=utf8
__author__ = 'lijian'
import setting
import logging
import os
from xml.dom import minidom
from utils import bcdUtil
from utils import byteUtil

info = {
    "boxNo": (),  # 控制箱编号
    "address": (),  # 终端地址
    "longitude": 0,  # 经度
    "latitude": 0,  # 纬度
    "lampEnable": True,  # 是否启用单灯
    "frequency": 1  # 单灯通信频点
}

uplink = {
    "slaveTimeout": 60,  # 终端等待从动站响应的超时时间
    "retry": 0,  # 重发数数
    "heartbeatCycle": 3,  # 心跳同期
    # 主动上报设置
    "initiative": {
        "realTime": False,  # 实时数据
        "history": False,  # 历史数据
        "event": False  # 事件数据
    }
}

network = {
    "server": {
        "ip": "127.0.0.1",
        "port": 9083
    },
    "gprs": {
        "apn": "cmnet",
        "simcard": "18682310672",
    }
}

poll = {
    "enable": False,
    "discover": False
}

plc = {
    "timeout": 10,
    "retry": 3
}

# 终端事件记录配置
eventConfig = {}

# 终端事件检测配置
eventDetectionConfig = {
    "commFailTime": 3,  # 终端通信故障检测间隔时间
    "routeFailTime": 3,  # 集中器路由板故障检测间隔时间
    "lampOnDelay": 1,  # 单灯正常开灯采集延时间
    "lampOffDelay": 1,  # 单灯正常关灯采集延时间
    "lampCurrentDelay": 10  # 单灯电流检测延时时间
}

# 单灯事件检测配置
lampThresholdConfig = {
    "maxCurrentThreshold": 10,  # 单灯电流过大事件电流限值(A)
    "maxCurrentRecover": 5,  # 单灯电流过大事件恢复电流限值(A)
    "minCurrentThreshold": 0.05,  # 单位电流过小事件电流限值(mA)
    "minCurrentRecover": 0.05,  # 单位电流过小事件恢复电流限值(mA)
    "lowPFThreshold": 50,  # 单灯电容故障事件故障功率因数限值
    "lowPFRecover": 50,  # 单灯电容故障事件故障恢复功率因数限值
    "breakdownCurrentThreshold": 0.05,  # 单灯灯具故障事件电流限值
    "breakdownCurrentRecover": 0.05,  # 单灯灯具故障事件恢复电流限值
    "burnCurrentThreshold": 0.05,  # 单灯熔丝故障事件电流限值
    "burnCurrentRecover": 0.05  # 单灯熔丝故障事件恢复电流限值
}

# 信息量检测间隔时间参数
rtuDetectionInterval = {
    "DI": 10,  # 单位ms
    "AI": 10,  # 单位ms
    "ammeter": 1  # 单位分钟
}

# 控制回路参数
rtuLoopParam = {
    "ctrlValid": [0] * 16,
    "saving": False,
    "level": 255
}


def updatePoll(enable, discover):
    poll["enable"] = enable
    poll["discover"] = discover

    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement
        pollEle = root.getElementsByTagName("poll")[0]

        pollEle.setAttribute("enable", "1" if poll["enable"] else "0")
        pollEle.setAttribute("discover", "1" if poll["discover"] else "0")

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readConfig():
    global info, network, poll

    if not os.path.exists(setting.CONFIG_FILE):
        logging.warn("%s not exist" % setting.CONFIG_FILE)
        return

    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement

        readBaseInfo(root)
        readUplink(root)
        readNetwork(root)
        readEventRecordConfig(root)
        readEventDetectionConfig(root)
        readLampThresholdConfig(root)
        readRtuDetectionInterval(root)
        readRtuLoopParam(root)
        readPoll(root)
        readPlc(root)

    except Exception as e:
        logging.error("parse %s error" % setting.CONFIG_FILE)


def readBaseInfo(root):
    try:
        infoEle = root.getElementsByTagName("info")[0]
        boxNo = int(infoEle.getElementsByTagName("boxNo")[0].firstChild.nodeValue)
        bcd = bcdUtil.numberToBcd(boxNo, 6)
        info["boxNo"] = tuple(bcd)

        address = int(infoEle.getElementsByTagName("address")[0].firstChild.nodeValue.encode("ISO-8859-1"))
        bcd = bcdUtil.numberToBcd(address, 8)
        info["address"] = tuple(bcd)

        info["frequency"] = int(infoEle.getElementsByTagName("frequency")[0].firstChild.nodeValue)

        lampEnable = infoEle.getElementsByTagName("lampEnable")[0].firstChild.nodeValue
        info["lampEnable"] = True if lampEnable == u"True" else False
        geometry = infoEle.getElementsByTagName("geometry")[0]
        info["longitude"] = int(geometry.getAttribute("longitude"))
        info["latitude"] = int(geometry.getAttribute("latitude"))
    except:
        logging.warn("read base info error")


def updateBaseInfo(value):
    global info
    info = value
    if not os.path.exists(setting.CONFIG_FILE):
        logging.warn("%s not exist" % setting.CONFIG_FILE)
        return

    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement
        infoEle = root.getElementsByTagName("info")[0]
        boxNoEle = infoEle.getElementsByTagName("boxNo")[0]
        boxNoEle.firstChild.nodeValue = bcdUtil.bcdToNumber(info["boxNo"])

        addrEle = infoEle.getElementsByTagName("address")[0]
        addrEle.firstChild.nodeValue = bcdUtil.bcdToNumber(info["address"])

        frequencyEle = infoEle.getElementsByTagName("frequency")[0]
        frequencyEle.firstChild.nodeValue = info["frequency"]

        lampEnableEle = infoEle.getElementsByTagName("lampEnable")[0]
        lampEnableEle.firstChild.nodeValue = info["lampEnable"]

        geometryEle = infoEle.getElementsByTagName("geometry")[0]
        geometryEle.setAttribute("latitude", "%d" % info["latitude"])
        geometryEle.setAttribute("longitude", "%d" % info["longitude"])

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readUplink(root):
    try:
        ele = root.getElementsByTagName("uplink")[0]
        uplink["slaveTimeout"] = int(ele.getAttribute("slaveTimeout"))
        uplink["retry"] = int(ele.getAttribute("retry"))
        uplink["heartbeatCycle"] = int(ele.getAttribute("heartbeatCycle"))

        iele = ele.getElementsByTagName("initiative")[0]
        uplink["initiative"]["realTime"] = int(iele.getAttribute("realTime").encode("ISO-8859-1"))
        uplink["initiative"]["history"] = int(iele.getAttribute("history").encode("ISO-8859-1"))
        uplink["initiative"]["event"] = int(iele.getAttribute("event").encode("ISO-8859-1"))

    except:
        logging.warn("read uplink error")


def updateUplink():
    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement

        ele = root.getElementsByTagName("uplink")[0]

        ele.setAttribute("slaveTimeout", "%d" % uplink["slaveTimeout"])
        ele.setAttribute("retry", "%d" % uplink["retry"])
        ele.setAttribute("heartbeatCycle", "%d" % uplink["heartbeatCycle"])

        iele = ele.getElementsByTagName("initiative")[0]
        iele.setAttribute("event", "%r" % uplink["initiative"]["event"])
        iele.setAttribute("history", "%r" % uplink["initiative"]["history"])
        iele.setAttribute("realTime", "%r" % uplink["initiative"]["realTime"])

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readNetwork(root):
    try:
        netWorkEle = root.getElementsByTagName("network")[0]
        serverEle = netWorkEle.getElementsByTagName("server")[0]
        network["server"]["ip"] = serverEle.getAttribute("ip").encode("ISO-8859-1")
        network["server"]["port"] = int(serverEle.getAttribute("port"))
        gprsEle = netWorkEle.getElementsByTagName("gprs")[0]
        network["gprs"]["apn"] = gprsEle.getAttribute("apn").encode("ISO-8859-1")
    except:
        logging.warn("read network error")


def updateNetwork(ip, port, apn):
    global info
    if not os.path.exists(setting.CONFIG_FILE):
        logging.warn("%s not exist" % setting.CONFIG_FILE)
        return

    network["server"]["ip"] = ip
    network["server"]["port"] = port
    network["gprs"]["apn"] = apn

    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement
        netWorkEle = root.getElementsByTagName("network")[0]

        serverEle = netWorkEle.getElementsByTagName("server")[0]
        serverEle.setAttribute("ip", ip)
        serverEle.setAttribute("port", "%d" % port)

        gprsEle = netWorkEle.getElementsByTagName("gprs")[0]
        gprsEle.setAttribute("apn", apn)

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readEventRecordConfig(root):
    try:
        eventRecordElement = root.getElementsByTagName("eventRecord")[0]

        eventElements = eventRecordElement.getElementsByTagName("event")
        for ele in eventElements:
            code = int(ele.getAttribute("code"))

            validity = False if ele.getAttribute("validity") == "0" else True
            importance = False if ele.getAttribute("importance") == "0" else True
            initiative = False if ele.getAttribute("initiative") == "0" else True

            eventConfig[code] = {"validity": validity, "importance": importance, "initiative": initiative}

    except:
        logging.warn("read eventRecordConfig error")


def updateEventRecordConfig():
    if not os.path.exists(setting.CONFIG_FILE):
        logging.warn("%s not exist" % setting.CONFIG_FILE)
        return

    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement

        parent = root.getElementsByTagName("eventRecord")[0]
        eventElements = parent.getElementsByTagName("event")

        for ele in eventElements:
            code = int(ele.getAttribute("code"))
            event = eventConfig[code]

            ele.setAttribute("validity", "%d" % event["validity"])
            ele.setAttribute("importance", "%d" % event["importance"])
            ele.setAttribute("initiative", "%d" % event["initiative"])

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readEventDetectionConfig(root):
    try:
        ele = root.getElementsByTagName("eventDetection")[0]

        eventDetectionConfig["commFailTime"] = int(ele.getAttribute("commFailTime"))
        eventDetectionConfig["routeFailTime"] = int(ele.getAttribute("routeFailTime"))
        eventDetectionConfig["lampOnDelay"] = int(ele.getAttribute("lampOnDelay"))
        eventDetectionConfig["lampOffDelay"] = int(ele.getAttribute("lampOffDelay"))
        eventDetectionConfig["lampCurrentDelay"] = int(ele.getAttribute("lampCurrentDelay"))
    except:
        logging.warn("read EventDetectionConfig error")


def updateEventDetectionConfig():
    if not os.path.exists(setting.CONFIG_FILE):
        logging.warn("%s not exist" % setting.CONFIG_FILE)
        return

    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement

        ele = root.getElementsByTagName("eventDetection")[0]

        ele.setAttribute("commFailTime", "%d" % eventDetectionConfig["commFailTime"])
        ele.setAttribute("routeFailTime", "%d" % eventDetectionConfig["routeFailTime"])
        ele.setAttribute("lampOnDelay", "%d" % eventDetectionConfig["lampOnDelay"])
        ele.setAttribute("lampOffDelay", "%d" % eventDetectionConfig["lampOffDelay"])
        ele.setAttribute("lampCurrentDelay", "%d" % eventDetectionConfig["lampCurrentDelay"])

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readLampThresholdConfig(root):
    try:
        ele = root.getElementsByTagName("lampThreshold")[0]

        lampThresholdConfig["maxCurrentThreshold"] = float(ele.getAttribute("maxCurrentThreshold"))
        lampThresholdConfig["maxCurrentRecover"] = float(ele.getAttribute("maxCurrentRecover"))

        lampThresholdConfig["minCurrentThreshold"] = float(ele.getAttribute("minCurrentThreshold"))
        lampThresholdConfig["minCurrentRecover"] = float(ele.getAttribute("minCurrentRecover"))

        lampThresholdConfig["lowPFThreshold"] = float(ele.getAttribute("lowPFThreshold"))
        lampThresholdConfig["lowPFRecover"] = float(ele.getAttribute("lowPFRecover"))

        lampThresholdConfig["breakdownCurrentThreshold"] = float(ele.getAttribute("breakdownCurrentThreshold"))
        lampThresholdConfig["breakdownCurrentRecover"] = float(ele.getAttribute("breakdownCurrentRecover"))

        lampThresholdConfig["burnCurrentThreshold"] = float(ele.getAttribute("burnCurrentThreshold"))
        lampThresholdConfig["burnCurrentRecover"] = float(ele.getAttribute("burnCurrentRecover"))

    except:
        logging.warn("read LampThresholdConfig error")


def updateLampThresholdConfig():
    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement

        ele = root.getElementsByTagName("lampThreshold")[0]

        ele.setAttribute("maxCurrentThreshold", "%d" % lampThresholdConfig["maxCurrentThreshold"])
        ele.setAttribute("maxCurrentRecover", "%d" % lampThresholdConfig["maxCurrentRecover"])

        ele.setAttribute("minCurrentThreshold", "%f" % lampThresholdConfig["minCurrentThreshold"])
        ele.setAttribute("minCurrentRecover", "%f" % lampThresholdConfig["minCurrentRecover"])

        ele.setAttribute("lowPFThreshold", "%f" % lampThresholdConfig["lowPFThreshold"])
        ele.setAttribute("lowPFRecover", "%f" % lampThresholdConfig["lowPFRecover"])

        ele.setAttribute("breakdownCurrentThreshold", "%f" % lampThresholdConfig["breakdownCurrentThreshold"])
        ele.setAttribute("breakdownCurrentRecover", "%f" % lampThresholdConfig["breakdownCurrentRecover"])

        ele.setAttribute("burnCurrentThreshold", "%f" % lampThresholdConfig["burnCurrentThreshold"])
        ele.setAttribute("burnCurrentRecover", "%f" % lampThresholdConfig["burnCurrentRecover"])

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readRtuDetectionInterval(root):
    try:
        ele = root.getElementsByTagName("rtuDetectionInterval")[0]

        rtuDetectionInterval["DI"] = int(ele.getAttribute("DI"))
        rtuDetectionInterval["AI"] = int(ele.getAttribute("AI"))
        rtuDetectionInterval["ammeter"] = int(ele.getAttribute("ammeter"))

    except:
        logging.warn("read RtuDetectionInterval error")


def updateRtuDetectionInterval():
    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement

        ele = root.getElementsByTagName("rtuDetectionInterval")[0]

        ele.setAttribute("DI", "%d" % rtuDetectionInterval["DI"])
        ele.setAttribute("AI", "%d" % rtuDetectionInterval["AI"])
        ele.setAttribute("ammeter", "%d" % rtuDetectionInterval["ammeter"])

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readRtuLoopParam(root):
    try:
        ele = root.getElementsByTagName("rtuLoopParam")[0]

        rtuLoopParam["saving"] = byteUtil.strToBool(ele.getAttribute("saving").encode("ISO-8859-1"))
        rtuLoopParam["level"] = int(ele.getAttribute("level"))

        ctrlValid = ele.getElementsByTagName("ctrlValid")[0]
        text = ctrlValid.firstChild.nodeValue.encode("ISO-8859-1")
        text = text.replace("\n", "")
        value = eval(text)
        rtuLoopParam["ctrlValid"] = value
    except:
        logging.warn("read RtuDetectionInterval error")


def updateRtuLoopParam():
    try:
        doc = minidom.parse(setting.CONFIG_FILE)
        root = doc.documentElement

        ele = root.getElementsByTagName("rtuLoopParam")[0]
        ele.setAttribute("saving", "%r" % rtuLoopParam["saving"])
        ele.setAttribute("level", "%d" % rtuLoopParam["level"])

        ctrlValid = ele.getElementsByTagName("ctrlValid")[0]
        ctrlValid.firstChild.nodeValue = rtuLoopParam["ctrlValid"]

        f = open(setting.CONFIG_FILE, 'w')
        doc.writexml(f, addindent='', newl='', encoding='utf-8')
    except Exception as e:
        logging.error("write %s error.%r " % (setting.CONFIG_FILE, e))


def readPoll(root):
    try:
        pollEle = root.getElementsByTagName("poll")[0]
        poll["enable"] = False if pollEle.getAttribute("enable") == u"0" else True
        poll["discover"] = False if pollEle.getAttribute("discover") == u"0" else True
    except:
        logging.warn("read poll error")


def readPlc(root):
    try:
        plcEle = root.getElementsByTagName("plc")[0]
        plc["timeout"] = int(plcEle.getAttribute("timeout"))
        plc["retry"] = int(plcEle.getAttribute("retry"))
    except:
        logging.warn("read plc error")


def checkRuntime():
    if not os.path.exists(setting.RUNTIME_PATH):
        os.mkdir(setting.RUNTIME_PATH)

    files = os.listdir(setting.CONFIG_PATH)
    for c in files:
        runtimeFilePath = os.path.join(setting.RUNTIME_PATH, c)
        configFilePath = os.path.join(setting.CONFIG_PATH, c)
        if not os.path.exists(runtimeFilePath):
            logging.info("copy %s to runtime" % c)
            os.system("cp %s %s" % (configFilePath, runtimeFilePath))
